﻿using Infrastructure.ElasticSearch.Enums;
using Nest;
using System.Collections.Generic;
using System.Linq;

namespace Infrastructure.ElasticSearch.ParentChilds
{
    public class NestBaseSpecification<T> : ISearchSpecification<ISearchRequest<T>> where T : class
    {
        private readonly string _path;
        private readonly List<ISearchSpecification<ISearchRequest<T>>> _queries;
        private readonly QueryPositionEnum _mustPosition;

        public NestBaseSpecification(string path, QueryPositionEnum mustPositon = QueryPositionEnum.Must)
        {
            _path = path;
            _queries = new List<ISearchSpecification<ISearchRequest<T>>>();
            _mustPosition = mustPositon;

        }

        public bool HasQuery()
        {
            return _queries.Any();
        }

        public void AddQuery(ISearchSpecification<ISearchRequest<T>> specification)
        {
            _queries.Add(specification);
        }

        public ISearchRequest<T> IsSatisfiedBy()
        {
            if (_mustPosition == QueryPositionEnum.Must)
            {
                return new SearchDescriptor<T>()
                .Query(q => q
                    .Nested(m => m
                        .Path(_path)
                        .Query(qq => qq
                            .Bool(b => b
                                .Must(
                                    _queries.Select(qu => qu
                                        .IsSatisfiedBy()
                                        .Query
                                    ).ToArray()
                                ).MustNot(
                                 _queries.Select(qu => qu
                                        .IsSatisfiedBy()
                                        .Query
                                    ).ToArray()
                                )
                            )
                        )
                    )
                );
            }
            else
            {
                return new SearchDescriptor<T>()
                .Query(q => q
                    .Nested(m => m
                        .Path(_path)
                        .Query(qq => qq
                            .Bool(b => b
                                .MustNot(
                                    _queries.Select(qu => qu
                                        .IsSatisfiedBy()
                                        .Query
                                    ).ToArray()
                                )
                            )
                        )
                    )
                );
            }

        }
    }
}
